今天開始連著三天,我會先介紹 conan 基礎操作,然後接著介紹 vcpkg。
今天的目標非常簡單:
開始之前,給大家看我的測試環境
我假設讀者已經具備基本的 C++ 開發知識,而且電腦上已經安裝好編譯器跟開發環境。
這份教學會專注在套件管理器(Package Manager)的使用上,其他部份就不特別詳細解釋了。當然,有問題歡迎留言,我一定回答。
最直接的安裝法是透過 pip (我們之前提過 Conan 是 Python 寫的嘛):
pip install conan
Debian、Ubuntu 比較新的發行版,會擋掉系統層級 pip 安裝,遇到的話可改用:
pipx install conan。
除此之外,也可以去抓獨立安裝包: https://conan.io/downloads
裝好之後,確認一下命令列有抓到conan:
conan --version
如果看到 Conan 版本印出來了,就是安裝成功,恭喜你完成第一步。
參考:Conan 官方的安裝文件: https://docs.conan.io/2.32/installation.html
第一次使用 Conan,要先讓它偵測你電腦上的 C++ 編譯器,產生預設的 Profile。
請打開命令列,輸入以下指令:
conan profile detect
這個指令跑完後,會產生一個組態檔案(Profile),放在你的用戶家目錄下面。
我在 Windows 11 上偵測出來是這樣:
[settings]
arch=x86_64
build_type=Release
compiler=msvc
compiler.cppstd=14
compiler.runtime=dynamic
compiler.version=194
os=Windows
我在 macOS 上面偵測出來是這樣:
[settings]
arch=armv8
build_type=Release
compiler=apple-clang
compiler.cppstd=gnu17
compiler.libcxx=libc++
compiler.version=17
os=Macos
每個人看到的內容可能會有些微不同,端看你的電腦當下安裝的是哪款編譯器。
這個檔案就是你的「預設組態檔」(default profile)
這份 profile 很重要。還記得 C++ 生態最大的特色嗎?有許許多多不同的編譯器跟版本,各個編譯器版本產生的二進位檔案經常互不相容。所以 Conan 就弄了一個編譯器組態來區分各種編譯器。
之後下達各種 conan 指令時,都可以藉由指定組態,讓 Conan 去驅動相對應的編譯工具鍊來執行工作。
以後我們會用正式術語 Conan Profile 來稱呼這個編譯器組態。
給資深工程師:這個 Profile 檔案是完全允許修改的,你可以隨意修改裡面的數值,你知道自己在改什麼就好。同時,同一台電腦上擁有多份 profile 來對應不同編譯器是很常見的。
接著來建立一個最基本的 CMake 專案。有兩個檔案 CMakeLists.txt 以及 main.cpp。
hello-conan/
├── CMakeLists.txt
└── src/
└── main.cpp
cmake_minimum_required(VERSION 3.15)
project(hello_conan CXX)
find_package(fmt REQUIRED)
find_package(nlohmann_json REQUIRED)
add_executable(hello src/main.cpp)
target_link_libraries(hello
PRIVATE fmt::fmt nlohmann_json::nlohmann_json)
請注意這就是一個標準的 CMake 專案,完全沒有任何 Conan 相關的字眼。
你可能會好奇:怎麼沒設定 C++ 標準?因為 Profile 裡已經有 compiler.cppstd 了,待會 Conan 產生的 toolchain 檔案會幫你設好。標準只在一個地方講一次就夠,重複寫反而容易兩邊對不上。
接著來寫 C++ 原始碼
#include <fmt/core.h>
#include <nlohmann/json.hpp>
int main() {
nlohmann::json j = {
{"name", "Conan"},
{"language", "Python"},
{"stars", 9000}
};
fmt::print("Hello, {}!\n", j["name"].get<std::string>());
fmt::print("{}\n", j.dump(2));
return 0;
}
檔案不大,只有寥寥數行,裡面刻意用了兩個第三方函式庫 fmt 以及 nlohmann json
目前專案是無法編譯的狀態,畢竟我們使用了外部函式庫,但是並沒有告訴編譯器要該去哪裡找函式庫呀。
下一步,就該 Conan 出場了。
接著我們往專案的根目錄添加一個檔案:conanfile.txt
hello-conan/
├── conanfile.txt
├── CMakeLists.txt
└── src/
└── main.cpp
conanfile.txt 這個檔案就是 Conan 的入口!
它是個純文字設定檔,請往裡面寫入以下內容:
[requires]
fmt/12.2.0
nlohmann_json/3.12.0
[generators]
CMakeDeps
CMakeToolchain
這個檔案的內容共分成兩個區塊:
[requires]區塊:
這裡寫我們想要導入的函式庫以及版本號碼,一個一行。這裡我選了 fmt(字串格式化)和 nlohmann_json(JSON),兩個都是 C++ 圈子裡人盡皆知的函式庫。
[generators]區塊:
這裡告訴 Conan 我們打算要用 CMake,請你準備和 CMake 對接。
CMakeDeps 會幫產生每個套件的 config 檔CMakeToolchain 會產生 conan_toolchain.cmake 和 CMakePresets.json
寫好 conanfile.txt 之後,請前往專案的根目錄輸入conan install指令,就能開始下載兩套函式庫囉
conan install . --output-folder=build --build=missing
--output-folder=build 則是告訴 Conan 請把產生的檔案放進 build 子目錄下。
--build=missing 參數的意思是:如果伺服器上找得到相容的二進位檔就直接下載,找不到的話,就現場編譯原始碼。如果沒有加這個參數,組態對不上時 Conan 會報錯誤。這是非常有可能發生的,畢竟C++編譯器的變化實在太多了。
在我的 Windows 上,兩個套件都能直接下載預先編譯好的檔案:
-------- Downloading 2 packages --------
fmt/12.2.0: Retrieving package 159b37... from remote 'conancenter'
nlohmann_json/3.12.0: Retrieving package da39a3... from remote 'conancenter'
...
Install finished successfully
此時你會看到 build 子目錄下多了許多檔案,都是 Conan 產生的。
接下來,我們就可以按照正常程序來編譯 CMake 專案囉!
那到底要怎麼讓 CMake 找到第三方函式庫的位置呢?秘密就藏在 conan_toolchain.cmake 裡面,我們只要傳入這個檔案,CMake 就可以找到所有它需要的資訊囉!
(CMAKE_TOOLCHAIN_FILE 給相對路徑時,CMake 是相對 build 目錄去找的,所以這裡直接寫檔名就好。)
Windows
$ cmake -S . -B build -G "Visual Studio 17 2022" -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
$ cmake --build build --config Release
macOS/Linux
$ cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
$ cmake --build build
編譯完成後,就可以看執行結果啦:
Hello, Conan!
{
"language": "Python",
"name": "Conan",
"stars": 9000
}
恭喜你,終於打通整條路了!回頭看,關鍵流程其實只有三步:
conan profile detect:告訴 Conan 你用哪個編譯器conan install . --build=missing:下載套件並產生 CMake 需要的檔案下一節開始,我們會講解 conan 怎麼跟其他 CMake 以外的建構系統合作。